package com.dff.jrfw;

import android.Manifest;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.MutableLiveData;

import com.dff.jrfw.common.Constant;
import com.dff.jrfw.databinding.ActivityStartBinding;
import com.dff.jrfw.dialog.CertOutTimeDialog;
import com.dff.jrfw.dialog.UpdateDialog;
import com.dff.jrfw.model.LoginAccountRecordModel;
import com.dff.jrfw.remote.ApiConfig;
import com.dff.jrfw.remote.ProgressResponseBody;
import com.dff.jrfw.remote.RetrofitUtils;
import com.dff.jrfw.service.WebPreloadService;
import com.dff.jrfw.utils.GsonUtils;
import com.dff.jrfw.utils.SharedPreferenceUtils;
import com.dff.jrfw.utils.TagAliasOperatorHelper;
import com.dff.jrfw.utils.TimeUtils;
import com.dff.jrfw.utils.ToastUtil;
import com.dff.jrfw.utils.Util;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.tencent.bugly.crashreport.CrashReport;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

import cn.com.infosec.mobile.android.IMSSdk;
import cn.com.infosec.mobile.android.managers.CertManager;
import cn.com.infosec.mobile.android.result.Result;
import cn.jpush.android.api.JPushInterface;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import static com.dff.jrfw.utils.TagAliasOperatorHelper.ACTION_SET;

public class StartActivity extends BaseActivity {

    private ActivityStartBinding binding;
    private static final int PERMISSON_REQUESTCODE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_start);
        if ("Test".equals(Constant.ENV)) {
            String[] branches = {
                    Constant.APP_H5,
                    Constant.APP_H5.replace("mobile", "mobile2"),
            };
            new AlertDialog.Builder(this)
                    .setTitle("请选择分支")
                    .setCancelable(false)
                    .setSingleChoiceItems(branches, 0, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            Constant.APP_H5 = branches[which];
                            doLogic();
                        }
                    })
                    .show();
        }else {
            doLogic();
        }
//        try {
//            String builder = "当前环境:" +
//                    Constant.ENV +
//                    "\n" +
//                    "版本号：" +
//                    getPackageManager().getPackageInfo(getPackageName(), 0).versionName +
//                    "\n" +
//                    "xinan:" +
//                    Constant.XINAN_HOST +
//                    "\n" +
//                    "h5:" +
//                    Constant.APP_H5 +
//                    "\n" +
//                    "bems:" +
//                    ApiConfig.BASE_URL_ONE +
//                    "\n" +
//                    "maps:" +
//                    ApiConfig.BASE_URL_TWO +
//                    "\n";
//            new AlertDialog.Builder(this)
//                    .setTitle("环境信息")
//                    .setMessage(builder)
//                    .setOnDismissListener(dialog -> doLogic())
//                    .show();
//        } catch (PackageManager.NameNotFoundException e) {
//            e.printStackTrace();
//        }
    }

    private void init() {
        ArrayList<String> permissions = new ArrayList();
        if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(this, android.Manifest.permission.READ_PHONE_STATE)) {
            permissions.add(android.Manifest.permission.READ_PHONE_STATE);
        }
        if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)) {
            permissions.add(android.Manifest.permission.CAMERA);
        }
        if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
        if (permissions.size() > 0) {
            String[] perms = new String[permissions.size()];
            ActivityCompat.requestPermissions(StartActivity.this, permissions.toArray(perms), PERMISSON_REQUESTCODE);
        } else {
            initXinAn();
        }
    }

    private void checkUpdate() {
        showLoading();
        RetrofitUtils.getService().getAppVersions(Constant.VERSION_URL).enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if (response.isSuccessful()) {
                    try {
                        JSONObject versionJson = new JSONObject(response.body().string());
                        JSONObject version = versionJson.getJSONObject(Constant.ENV);
                        int verCode = version.getInt("verCode");
                        String verName = version.getString("verName");
                        if (verCode > getPackageManager().getPackageInfo(getPackageName(), 0).versionCode) {
                            hideLoading();
                            String apkPath = version.getString("apkPath");
                            update(apkPath, verName);
                        } else {
                            init();
                        }
                    } catch (IOException | JSONException | PackageManager.NameNotFoundException e) {
                        init();
                    }
                } else {
                    init();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                init();
            }
        });
    }

    private void update(String url, String name) {
        Util.logLength("更新", url);
        MutableLiveData<Integer> progress = new MutableLiveData<>();
        AtomicBoolean downloadFlag = new AtomicBoolean(true);
        UpdateDialog updateDialog = new UpdateDialog(this, progress, downloadFlag);
        updateDialog.show();
        new OkHttpClient.Builder().addInterceptor(chain -> {
            okhttp3.Response proceed = chain.proceed(chain.request());
            return proceed.newBuilder()
                    .body(new ProgressResponseBody(proceed.body(), (bytesRead, contentLength, done) -> progress.postValue((int) (bytesRead * 10000 / contentLength))))
                    .build();
        })
                .build()
                .newCall(new Request.Builder().url(url).build())
                .enqueue(new okhttp3.Callback() {
                    @Override
                    public void onFailure(okhttp3.Call call, IOException e) {
                        ToastUtil.toast("更新失败：" + e.getMessage());
                    }

                    @Override
                    public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
                        if (response.isSuccessful()) {
                            ResponseBody body = response.body();
                            if (body != null) {
                                InputStream inputStream = body.byteStream();
                                File file = new File(getApplication().getCacheDir(), name);
                                OutputStream outputStream = new FileOutputStream(file);
                                byte[] buffer = new byte[4096];
                                int len;
                                while ((len = inputStream.read(buffer)) != -1) {
                                    if (downloadFlag.get()) {
                                        outputStream.write(buffer, 0, len);
                                    } else {
                                        break;
                                    }
                                }
                                inputStream.close();
                                outputStream.close();
                                runOnUiThread(() -> {
                                    updateDialog.dismiss();
                                    if (!downloadFlag.get()) {
                                        finish();
                                    } else {
                                        install(file);
                                    }
                                });
                            }
                        }
                    }
                });
    }

    private void install(File file) {
        Util.logLength("xxx", "install " + file.getPath());
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Uri contentUri = FileProvider.getUriForFile(this, getPackageName() + ".fileProvider", file);
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
        }
        startActivityForResult(intent, 0);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 0) {
            Util.logLength("xxx", resultCode + "");
            finish();
        }
    }

    private void gotoLogin() {
        String json = (String) SharedPreferenceUtils.getInstance().get(StartActivity.this, Constant.LOGIN_ACCOUNT_RECORD, "");
        LoginAccountRecordModel loginAccountRecordModel = GsonUtils.gsonToBean(json, LoginAccountRecordModel.class);
        if (loginAccountRecordModel != null && loginAccountRecordModel.getLoginRecord() != null && loginAccountRecordModel.getLoginRecord().size() > 0) {
            ArrayList<String> loginRecord = loginAccountRecordModel.getLoginRecord();
            finish();
            LoginTwoActivity.callMe(StartActivity.this, loginRecord);
        } else {
            finish();
            LoginActivity.callMe(StartActivity.this, null);
        }
    }

    private void doLogic() {
        startService(new Intent(this, WebPreloadService.class));
        CrashReport.initCrashReport(this, "da55260c42", false);

        // true则会打印debug级别的日志，false则只会打印warning级别以上的日志
        JPushInterface.setDebugMode(ApiConfig.J_PUSH_DEBUG);
        JPushInterface.init(this);
        checkUpdate();
//        MainActivity.callMe(this);
//        VersionActivity.callMe(this);
//        finish();
    }


    //检查证书是否存在，存在则判断证书有效期
    private void checkCert(String username) {
        CertManager certManager = new CertManager(this);
        boolean certExist = certManager.isCertExist(username);
        if (certExist) {
            showLoading();
            certManager.getStatusOnLine(username, new Result.ResultListener() {
                @Override
                public void handleResult(Result result) {
                    hideLoading();
                    String resultID = result.getResultID();
                    if (resultID.equals(Result.STATUS_EFFECTIVE)) {    //证书有效
                        String endTime = certManager.getCertField(username, 7);
                        try {
                            long endTimeLong = TimeUtils.getTimeStamp(endTime);
                            long currentTime = TimeUtils.getCurTimeMills();
                            long restTime = endTimeLong - currentTime;
                            if (restTime > 0) {
                                gotoLogin();
                            } else {
                                hideLoading();
                                CertOutTimeDialog certOutTimeDialog = new CertOutTimeDialog(StartActivity.this, username);
                                certOutTimeDialog.show();
                            }
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    } else {
                        boolean deleteCert = certManager.deleteCert(username);
                        if (deleteCert) {
                            gotoLogin();
                        } else {
                            hideLoading();
                            ToastUtil.toast("本地证书删除失败");
                        }
                    }
                }
            });
        } else {
            gotoLogin();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (PERMISSON_REQUESTCODE == requestCode) {
            boolean flag = true;
            for (int i = 0; i < permissions.length; i++) {
                if (PackageManager.PERMISSION_GRANTED != grantResults[i]) {
                    flag = false;
                    break;
                }
            }
            if (!flag) {
                ToastUtil.toast("权限被拒绝");
                finish();
            } else {
                initXinAn();
            }
        }
    }

    private void initXinAn() {
        showLoading();
        //信安SDK初始化
        IMSSdk.mContext = getApplicationContext();
        Log.i("TAG", "设备标记: ".concat(IMSSdk.deviceIdentifier()));
        // 没有初始化,需要先保证初始化成功
        IMSSdk.initialization(getApplicationContext(), Constant.XINAN_HOST, Constant.XIN_AN_CERT, Constant.APP_ID, Constant.APP_SECRET, new Result.ResultListener() {
            @Override
            public void handleResult(Result result) {
                hideLoading();
                if (Result.OPERATION_SUCCEED.equals(result.getResultID())) {
                    Log.i("TAG", "初始化结果: " + result.getResultDesc());
                    // 打印出IMSDK中的可用信息
                    Log.i("TAG", "SKD版本: ".concat(IMSSdk.version()));
                    Log.i("TAG", "设备标记: ".concat(IMSSdk.deviceIdentifier()));
                    Log.i("TAG", "QRCode有效期(毫秒): ".concat(String.valueOf(IMSSdk.getQRCodeExpireMillSeconds())));
                    Log.i("TAG", "签章图片大小(KB): ".concat(String.valueOf(IMSSdk.getSealerImageSize())));
                    Log.i("TAG", "注册码有效期(毫秒): ".concat(String.valueOf(IMSSdk.getSignCodeExpireMillSeconds())));
                    Log.i("TAG", "是否强制更新APP: ".concat(String.valueOf(IMSSdk.isAppForceUpdate())));
                    Log.i("TAG", "证书是否可用: ".concat(String.valueOf(IMSSdk.isCertAvailable())));
                    Log.i("TAG", "是否为协同签名: ".concat(String.valueOf(IMSSdk.isCollaborative())));
                    Log.i("TAG", "是否为信安世纪协同算法: ".concat(String.valueOf(IMSSdk.isInfosecCollaborative())));
                    Log.i("TAG", "是否为双证: ".concat(String.valueOf(IMSSdk.isPairedCert())));
                    Log.i("TAG", "PDF签章是否可用: ".concat(String.valueOf(IMSSdk.isPDFAvailable())));
                    Log.i("TAG", "PDF签章是否为服务端模式: ".concat(String.valueOf(IMSSdk.isServerPDFMode())));
                    Log.i("TAG", "数字签名是否可用: ".concat(String.valueOf(IMSSdk.isSignAvailable())));
                    Log.i("TAG", "动态令牌是否可用: ".concat(String.valueOf(IMSSdk.isTokenAvailable())));
                    IMSSdk.setNetworkTimeout(500000);
                    String curLoginAccount = (String) SharedPreferenceUtils.getInstance().get(StartActivity.this, Constant.CURRENT_LOGIN_ACCOUNT, "");
                    if (!TextUtils.isEmpty(curLoginAccount)) {
                        checkCert(curLoginAccount);
                    } else {
                        gotoLogin();
                    }
                } else {
                    Log.i("TAG", "初始化结果: " + result.getResultDesc());
                    new AlertDialog.Builder(StartActivity.this)
                            .setMessage("信安初始化失败:" + result.getResultDesc())
                            .setNegativeButton("退出", (dialog, which) -> {
                                dialog.dismiss();
                                finish();
                            })
                            .setPositiveButton("再试一次", (dialog, which) -> {
                                dialog.dismiss();
                                initXinAn();
                            })
                            .create()
                            .show();

                }
            }
        });
    }
}